var $ = window.$;
var jade = require('jade');
var Promise = require('bluebird');
var path = require('path');
var animate = require('../../util/animate');
var event = require('../../core/event');
var util = require('../../util/index');
var uiUtil = require('../../util/ui');
var config = require('../../core/config');
var notify = require('../notify/ui');
var note = require('../note/manager');
var Log = require('../../util/logger');
var fs = require('fs');
var exec = require("child_process").execFile;
var _inited = false;

/**
 * 上传
 * 由下面子页组成
 * 1. 说明
 * 2. 文件清单, 对比本地的缓存, 自动勾选有变化的部分
 * 3. 上传进度
 */

var ret = {
	init: function(){
		if(_inited){
			return;
		}
		this.uploading = false;  //正在上传
		//event.bind(event.events.key.up, 'upload_ui', this);
		event.lock('key', 'upload_ui');
		_inited = true;
	},

	setManager: function (ma) {
		this.manager = ma;
	},

	onEvent: function(e, param){
		/*if(param.key == 27){
			this.hide();
			return event.result.stopAll;
		}*/
	},

	doUpload: function() {
		if(this.pending.length == 0){
			this.finishUpload();
			return;
		}
		var idx = this.pending.shift();
		var file = this.files[idx];
		var hash = this.md5[idx];
		var self = this;

		this.manager._getUploadSign({
			name: hash,
			cid: this.cid,
			ver: 2
		}).then(function(data) {
			if(!data || data.code == -1){
				notify.addNotify({
					msg: config.i18n('err15'),
					err: true
				});
				return this.emptyFunc();
			}else if(data.code == -2){
				notify.addNotify({
					msg: config.i18n('err16'),
					err: true
				});
				return this.emptyFunc();
			}else if(data.code == -3){
				notify.addNotify({
					msg: config.i18n('err17'),
					err: true
				});
				return this.emptyFunc();
			}else if(data.code == -4){
				notify.addNotify({
					msg: config.i18n('err18'),
					err: true
				});
				return this.emptyFunc();
			}else if(data.code == 0){
				//参数正常, 传到cdn
                if(file.indexOf(".mc") > 0 && self.packedFileName){
                    file = self.packedFileName;
                }
				return self.manager._uploadToCDN({
					file:{
						file: file,
						content_type : 'application/octet-stream'
					},
					policy: data.data.policy,
					signature: data.data.signature
				});
			}
		}).then(function(data) {
			if(!data || data.code != 200){
				if(data){
					Log.e("upload error: "+data.msg, "Upload");
				}else{
					Log.e("CDN no response", "Upload");
				}
				return this.emptyFunc(); //随便抛个错误
			}
			Log.i("Upload succ:"+self.files[idx], "Upload");
			//UI更新
			var node = self.parent.find('#dialog_upload_list li').eq(idx);
			node.removeClass('curr').addClass('done');
			if(node.find('em').hasClass('on')){
				self.oldlist[hash] = true;
			}else{
				self.oldlist[hash] = false;
			}
			var percent = (self.pendingCount - self.pending.length) * 100 / self.pendingCount;
			self.parent.find('#dialog_progress').css('width', percent +'%');
			setTimeout(function() {
				self.doUpload();
			}, 50);  //50ms给UI刷新
		}).catch(function(e) {
			//出错就中断
			Log.e("upload error: internal", "Upload");
			self.pending.unshift(idx); //重新塞回去
			self.finishUpload();
		});
	},


	startUpload: function () {
		//先检查一下能否开始
		if(!this.files || !this.md5){
			return;  //这是错误, 不用提示
		}
		var curr = this.parent.find('#dialog_upload_list .curr');
		if(!curr.size()){
			notify.addNotify({
				msg: config.i18n('err14')
			});
			return;
		}
		var btn = this.parent.find(".g_bt span");
		btn.eq(1).html("Wait");
		this.uploading = true;

		notify.showWaiting(true);
		var len = curr.size();
		this.pending = [];
		this.pendingCount = len;
		for(var i=0;i<len;i++){
			this.pending.push(curr.eq(i).index());  //把选择的文件序号加入
		}
		Log.i("Start upload, count:"+len, "Upload");
		this.doUpload();
	},

    packMce : function(file){
		var baseName = file.substring(0, file.lastIndexOf("."));
		var packedFn = baseName + ".zip";
		if(util.createZip(file, packedFn)){
			this.packedFileName = packedFn;
		}
		/*var cmd = util.getPath("node_modules") + "/zip.exe";
		var args = ["-j"];
		var baseName = file.substring(0, file.lastIndexOf("."));
		var mapDir = path.dirname(file);
		var packedFn = baseName + ".zip";
		args.push(packedFn);
		args.push(file);
		var self = this;
		this.packedFileName = null;
		exec(cmd, args, {cwd : mapDir},function(stdin, stdout,error){
			if(!error){
				self.packedFileName = packedFn;
				defer.resolve();
			}else{
				defer.reject("failed to create zip:"+file);
			}
		});*/
    },

	finishUpload: function() {
		if(this.pending.length){
			//还有剩余file, 未成功
			notify.showWaiting(false);
			this.uploading = false;

			this.parent.find('#dialog_progress').css('width', '0');
			var btn = this.parent.find(".g_bt span");
			btn.eq(1).html("Start");
			notify.addNotify({
				msg: config.i18n("up08")
			});
			Log.i("Upload fail, left:"+this.pending.length, "Upload");
		}else{
			//成功, 上传最终列表
			var list = [];
			var newhash = '';
			for(var i=0;i<this.files.length;i++){
				var _name = path.basename(this.files[i]);
				list.push({
					name: _name,
					hash: this.md5[i],
					size: util.fileSize(this.files[i])
				});
				if(_name.indexOf('.mce') > 0 || _name.indexOf('.mc') > 0){
					newhash = this.md5[i];
				}
			}
			var conf = {
				cid: this.cid,
				raw: JSON.stringify(list),
				hash: newhash,
				ver: 2
			};
			var chart = note.getNote('main');
			conf.diff = chart.meta.version;
			conf.mode = chart.meta.mode;
			var grid = require('../grid/manager');
			conf.length = Math.round(grid.getMaxNoteTime() / 1000);

			var self = this;
			this.manager._sendUploadConfirm(conf).then(function(data) {
				notify.showWaiting(false);
				self.uploading = false;
				self.parent.find('#dialog_progress').css('width', 0);

				var btn = self.parent.find(".g_bt span");

				if(!data || data.code != 0){
					if(data){
						Log.e("upload confirm fail:"+data.code, "Upload");
					}else{
						Log.e("upload confirm ", "Upload");
					}
					//前面检查过一次参数, 如果这里再发生错误, 一律是后台问题
					btn.eq(1).html("Start");
					notify.addNotify({
						msg: config.i18n('err15'),
						err: true
					});
				}else{
					notify.addNotify({
						msg: config.i18n("up07")
					});
					Log.i("upload all success", "Upload");
				}

			});
		}
		//无论上传结果, 都要写入一次oldhash
		var oldhash = note.getFilePath('old.hash');
		util.saveJson(oldhash, this.oldlist);
	},

	show: function(){
		var tmpl = jade.compileFile('./tmpl/upload/dialog.jade');
		var html = tmpl({config: config});
		$('#dialog_layer').append(html);

		var self = this;
		this.parent = $('#dialog_upload');

		this.parent.find('#dialog_upload_list').on('click', 'li', function(e) {
			if(e.target.tagName == 'EM'){
				var node = $(e.target);
				node.toggleClass('on');
				if(!node.hasClass('on')){
					$(this).removeClass('curr');
				}
			}else{
				$(this).toggleClass('curr');
			}
		});

		this.parent.on('click','.g_barhead i', function () {
			if(self.uploading){
				return;
			}
			self.hide();
		});

		this.parent.on('click','.g_click', function(){
			var target = $(this);
			var type = target.data('type');
			if(type == 'ok'){
				if(self.uploading){
					return;
				}
				//启动上传
				self.startUpload();
			}else if(type == 'back'){
				if(self.uploading){
					return;
				}
				var chart = note.getNote('main');
				util.setJsonChainValue(chart, 'meta.id', 0);
				util.setJsonChainValue(chart, 'meta.song.id', 0);
				self.hide();
				event.trigger(event.events.file.upload);
			}else if(type == 'mark'){
				self.parent.find("#dialog_upload_list li em").toggleClass('on');
			}else if(type == 'high'){
				self.parent.find("#dialog_upload_list li").toggleClass('curr');
			}
		});

		this.parent.show();
		uiUtil.dialogInc();
		notify.showWaiting(true);
		animate.normalScaleIn(this.parent).then(function() {
			//数据量较大, 放到回调里来初始化
			var files = note.getAllFileAbs('main');  //因为是当前diff, 所有files里只有一个唯一的mce或者mc
			if (!files) {
				notify.showWaiting(false);
				notify.addNotify({
					msg: config.i18n('err14')
				});
				return;
			}
			var extra = note.getFilePath("data.zip");
			if(fs.existsSync(extra)){
				files.push(extra);
			}
			//meta
			var chart = note.getNote('main');
			self.cid = chart.meta.id;
			self.sid = chart.meta.song.id;  //外面检查过了, 肯定存在
			self.files = files;  //全部文件列表

			//mce, 变成mc和zip
			return note.exportUpload();
		}).then(function() {
			self.files[0] = util.ensureSuffix(self.files[0], 'mc');  //这个是存在的
			self.packMce(self.files[0]);

			//加载已上传文件列表
			var oldhash = note.getFilePath('old.hash');
			var oldlist = util.loadJsonSync(oldhash) || {};

			self.oldlist = oldlist;
			//计算所有文件的hash
			var hash = [];
			for (var i = 0; i < self.files.length; i++) {
				hash.push(util.fileMd5(self.files[i]));
			}

			return Promise.all(hash);
		}).then(function (ret) {
			self.md5 = ret;  //全部文件对应的md5值
			var html = [];
			for(var i=0;i<ret.length;i++){
				var size = util.fileSize(self.files[i]);
				var cls = '', mcls = 'class="on"';
				//没上传过, 或hash不一致
				var old = self.oldlist[ret[i]];
				if(typeof old == 'undefined'){
					cls = 'class="curr"';
				}else if(old === false){
					mcls = '';
				}

				html.push('<li '+cls+'><em '+mcls+'></em><span>'+path.basename(self.files[i])+'</span><i>'+util.getFormatSize(size)+'</i></li>');
			}

			self.parent.find('#dialog_upload_list').html(html.join(''));
			notify.showWaiting(false);

		}).catch(function(e){
			Log.e(e, "Upload");
		});
		event.trigger(event.events.global.blur);

	},

	hide: function(){
		var self = this;
		if(!this.parent){
			return;
		}
		animate.normalScaleOut(this.parent).then(function(){
			self.parent.remove();
			self.parent = null;
			uiUtil.dialogDec();
			event.unbind(event.events.key.up, 'upload_ui');
		});
		event.unlock();
		_inited = false;
	}
};

module.exports = ret;
